//#define __FORCE_TRACE__
//#define __FORCE_DEBUG__
//#define __FORCE_INFO__
#define THIS_FILE "ia\fn_reinforcementAirborne.sqf"
#include <tmf_constants.h>
#include <tmf_macros.h>

TRACE_1("Start",_this);
TMFPROFILERSTART;

private ["_instance","_side","_type","_startpoint","_target_pos","_side_variable","_transport_type","_transport_capacity","_number_vehicles","_parachute_type"
		,"_make_jump","_stop_it","_delveccrew","_unit_type","_target_radius","_vgrp","_reinf_arr","_wp","_stop_me","_checktime","_reinf_timeout_delay"
		,"_has_dropped_troops","_timeToLive","_paragrp","_para","_vec_arr","_last_pos","_next_check","_respawn_marker"];

if !(isServer || (!isDedicated && !hasInterface)) exitWith { ERROR("Reinforcement is server or HC only!"); };

DEFAULT_PARAM(_instance_id,0,TMF_SERVER_INSTANCE_ID);
DEFAULT_PARAM(_target_pos,1,ARR_3(0,0,0));
DEFAULT_PARAM(_side,2,GVAR(SIDE_ENEMY));
DEFAULT_PARAM(_units,3,[]);
DEFAULT_PARAM(_transport_type,4,"");
DEFAULT_PARAM(_target_radius,5,200);
DEFAULT_PARAM(_startpoint,6,[]);
DEFAULT_PARAM(_landing,7,false);

_fly_in_height = ["CHOPPER_FLY_IN_HEIGHT",100] call FFUNC(getFrameworkValue);
_reinf_timeout_delay = ["REINFORCEMENT_TIMEOUT_DELAY",600] call FFUNC(getFrameworkValue);


_range = ["REINF_AIRBORNE_RANGE",[3500,4500]] call FFUNC(getFrameworkValue);
_side = [_side] call FFUNC(getSide);

if (count _startpoint <= 0) then {
	_startpoint = [_target_pos,(_range select 1),(_range select 0)] call FFUNC(getRanAirPointCircle);
	while {{ _vec =_x; if (_vec isKindOf "Man") then { isPlayer _vec } else { {isplayer _x} count (crew _vec) > 0 } } count (_startpoint nearEntities [["CAManBase","LandVehicle","Air"], 500]) > 0} do {
		_startpoint = [_target_pos,(_range select 1),(_range select 0)] call FFUNC(getRanAirPointCircle);
	};
} else {
	// We still give some randomness
	_startpoint = [_startpoint,100,10] call FFUNC(getRanAirPointCircle);
};
_startpoint set [2,300];

if (count _units <= 0) then {
	_side_variable = format["INFANTRY_GROUP_%1",toUpper(str(_side))];
	_units = [_side_variable,[]] call FFUNC(getFrameworkValue);
};

_side_variable = format["AIR_TRANSPORT_%1",toUpper(str(_side))];
if (_transport_type == "" || {!isClass(configFile/"CfgVehicles"/_transport_type)}) then {
	_transport_type = [_side_variable,"I_Heli_Transport_02_F"] call FFUNC(getFrameworkValue);
};
if (!isClass(configFile/"CfgVehicles"/_transport_type)) exitWith {ERROR_1("Invalid Transport Type",_transport_type);};
_transport_capacity = getNumber(configFile/"CfgVehicles"/_transport_type/"transportsoldier");
if (_transport_capacity < (count _units)) then {
	TRACE_1("Not enough room for units",ARR_2(_transport_type,_transport_capacity));
	for "_i" from (_transport_capacity - 1) to ((count _units) - 1) step 1 do {
		_units set [_i, "XxDeLxX"];
	};
	_units = _units - ["XxDeLxX"];
};

_cdir = [_startpoint, _target_pos] call FFUNC(DirTo);
_vec_arr = [_instance_id,_transport_type,_side,_startpoint,0,[],_cdir] call FFUNC(spawnVehicle);

_vehicle = _vec_arr select 0;
_vgrp = _vec_arr select 2;

[_vehicle] call FFUNC(disableAIScripts);
{
	_x disableAI "TARGET";
	_x disableAI "AUTOTARGET";
	_x AllowFleeing 0;
	[_x] call FFUNC(disableAIScripts);
} foreach crew _vehicle;
_vgrp selectLeader (driver _vehicle);


_marker_text = "STR_MF_UNKNOWNAIRCONTACT";
_marker_color = "ColorRed";
_marker_type = "u_air";
If ([_side,GVAR(own_side)] call FFUNC(equalSide)) then {
	_marker_color = "ColorGreen";
	_marker_text = "STR_MF_REINFORCEMENTAIRCONTACT";
	_marker_type = "b_air";
};
[_instance_id,_vehicle,["ICON", _marker_color,[0.9,0.9], _marker_text,0,_marker_type]] call FFUNC(addObjectMarker);
		
_vehicle lock true;
sleep 5.012;
_vehicle flyInHeight _fly_in_height;


TRACE_1("Vehicle Info",ARR_4(typeof _vehicle, count crew _vehicle, _vgrp, _side));

_reinf_arr = [_vgrp, _vehicle, crew _vehicle, time, _target_pos];

_reinforcements = [_instance_id,"REINFORCEMENT_GROUPS",[]] call FFUNC(getMissionVar);
_reinforcements set [count _reinforcements,_reinf_arr];
[_instance_id,"REINFORCEMENT_GROUPS",_reinforcements] call FFUNC(setMissionVar);

_vgrp call FFUNC(deleteWaypoints);

_wp = _vgrp addWaypoint [_target_pos, 0];
_wp setWaypointBehaviour "CARELESS";
_wp setWaypointSpeed "FULL";
_wp setwaypointtype "MOVE";
_wp setWaypointFormation "VEE";
_vgrp setCurrentWayPoint _wp;
_vehicle flyInHeight _fly_in_height;
_wp = _vgrp addWaypoint [_startpoint, 0];
_wp setWaypointBehaviour "CARELESS";
_wp setWaypointSpeed "FULL";
_wp setwaypointtype "MOVE";

(driver _vehicle) doMove _target_pos;
sleep 10.0231;

_stop_me = false;
_checktime = time + _reinf_timeout_delay;
_has_dropped_troops = false;
// While we didn't arrive at destination yet.
_last_pos = position _vehicle;
_next_check = time + (_reinf_timeout_delay / 10);
while {!_stop_me && alive _vehicle && canMove _vehicle && (([_target_pos,_vehicle] call FFUNC(distTo)) > 500)} do {
	if (isNull _vehicle || !alive _vehicle || !alive (driver _vehicle)) exitWith { 
		_stop_me = true;
	};
	sleep 0.01;
	// If it took too much time for the vehicle to arrive, we kill it.
	if (time > _checktime) then {
		if (([_target_pos,_vehicle] call FFUNC(distTo)) > 500) then {
			[_vehicle, 1 + random 1] spawn FFUNC(delVecCrew);
			_stop_me = true;
			TRACE_1("Vehicle timed out",ARR_3(time,_checktime, ARR_2(_target_pos,_vehicle) call FFUNC(distTo)));
		} else {
			_checktime = time + 9999999;
		};
	};
	if (_next_check < time) then {
		_next_check = time + (_reinf_timeout_delay / 10);
		if ((_last_pos distance _vehicle) < 20) then {
			(driver _vehicle) doMove _target_pos;
		};
		_last_pos = position _vehicle;
	};
	sleep 2.023;
};
TRACE_1("Vehicle in reach or stopped",ARR_3(alive _vehicle, canMove _vehicle, ARR_2(_target_pos,_vehicle) call FFUNC(distTo)));
if (_stop_me) exitWith { ERROR("Forced stopping - Vehicle destroyed or did not reach destination",ARR_3(alive _vehicle, canMove _vehicle, ARR_2(_target_pos,_vehicle) call FFUNC(distTo)))};

sleep 0.534;

_side_variable = format["PARACHUTE_%1",toUpper(str(_side))];
_parachute_type = [_side_variable,"NonSteerable_Parachute_F"] call FFUNC(getFrameworkValue);

// If we reach this test, normally everyone is alive, but we check it for safety :)
// Otherwise we kill everyone for safety too :)
if (!isNull _vehicle && alive _vehicle && !_stop_me && (([_target_pos,_vehicle] call FFUNC(distTo)) <= 500 || !(canMove _vehicle))) then {
	TRACE_1("Starting to make paras",_vgrp);
	if (count _units > 0) then {
		_respawn_marker = tolower(format["respawn_%1",str(_side)]);
		_paragrp = [_instance_id, _units,_side,(getMarkerPos _respawn_marker),0] call FFUNC(spawnGroup);
		TRACE_1("Ejecting paras", ARR_3(_parachute_type, _paragrp,count (units _paragrp)));
		{
			if (alive _vehicle && ((getPos _vehicle) select 2) > 20) then {
				_para = createVehicle [_parachute_type, position _vehicle, [], 20, 'NONE'];
				_para setpos [(position _vehicle) select 0,(position _vehicle) select 1,((position _vehicle) select 2)- 10];
				_para setDir random 360;
				_x assignAsDriver _para;
				_x moveInDriver _para;
				sleep 0.551;
			};
		} foreach units _paragrp;
		
		_paragrp allowFleeing 0;
		_paragrp setCombatMode "RED";
		_paragrp setBehaviour "AWARE";
		sleep (5 + random 10);
		[_paragrp, _target_pos,_target_radius] spawn FFUNC(patrol);
		TRACE_1("All units ejected",ARR_2(_paragrp,count (units _paragrp)));
	} else {
		TRACE_1("No units to drop",ARR_2(_vgrp,_units));
	};
	sleep 0.112;
	
	_timeToLive = time + _reinf_timeout_delay;
	
	[_vgrp] call FFUNC(deleteWaypoints);
	_wp = _vgrp addWaypoint [_startpoint, 100];
	_wp setWaypointBehaviour "CARELESS";
	_wp setWaypointSpeed "FULL";
	_wp setWaypointType "MOVE";
	_vgrp setCurrentWaypoint _wp;
	
	(driver _vehicle) doMove _startpoint;
	
	_last_pos = position _vehicle;
	_next_check = time + (_reinf_timeout_delay / 10);
	while {(_startpoint distance _vehicle) > 400 && (_timeToLive > time)} do {
		if (isNull _vehicle || !alive _vehicle || !alive (driver _vehicle) || !canMove _vehicle) exitWith {};
		if (_next_check < time) then {
			_next_check = time + (_reinf_timeout_delay / 10);
			if ((_last_pos distance _vehicle) < 20) then {
				(driver _vehicle) doMove _target_pos;
			};
			_last_pos = position _vehicle;
		};
		sleep 5.123;
	};
	
	TRACE_1("Destroying the vehicle and crew",_vgrp);
	if (!isNull _vehicle && (_startpoint distance _vehicle) > 400) then {
		[_vehicle, 240 + random 100] spawn FFUNC(delVecCrew);
	} else {
		[_vehicle] spawn FFUNC(delVecCrew);
	};
	// We delete crews which might have exited the vehicle
	{
		if (!isnull _x && {vehicle _x == _x}) then {
			TRACE_1("Delete crew outside of vehicle",_x);
			deleteVehicle _x;
		};
	} foreach (_reinf_arr select 2);
} else {
	TRACE_1("Deleting the reinforcement vehicle",_vgrp);
	[_vehicle, 240 + random 100] spawn FFUNC(delVecCrew);
};

TRACE("End");
TMFPROFILERSTOP;